#ifndef FACTORY_H_INCLUDED
#define FACTORY_H_INCLUDED

#include <map>
#include "Singleton.h"
#include <string>

namespace OpenNano
{
    template <class TCreator>
    class OPENNANO_EXPORT FactoryT
    {
        friend class Singleton < FactoryT <TCreator> >;

        public:

            virtual ~FactoryT();
            const TCreator& create( std::string classId ) const;
            template < class TDerivedCreator > bool registerCreator( std::string classId);

        private:

            FactoryT();
            std::map< std::string, TCreator* > _creators;
    };

    template <class TCreator>
    FactoryT < TCreator >::FactoryT()
    {
    }

    template <class TCreator>
    FactoryT < TCreator >::~FactoryT()
    {
    }

    template <class TCreator>
    const TCreator& FactoryT < TCreator >::create( std::string classId) const
    {
        typename  std::map< std::string, TCreator* >::const_iterator ite( _creators.find( classId ) ) ;
        if( ite != _creators.end() )
		{
			return *ite->second ;
		}

		static TCreator creator ;
		return creator ;
    }


    //-------------------------------------------------------------------------
	// registerCreator
	//-------------------------------------------------------------------------
	template< class TCreator >
	template< class TDerivedCreator >
	bool
		FactoryT< TCreator >::registerCreator( std::string classId )
	{
		static TDerivedCreator creator ;
		_creators[classId] = &creator ;
		return true ;
	}

}

#endif // FACTORY_H_INCLUDED
